﻿using System;
using System.Linq;

namespace Web7.Logging
{
	/// <summary>
	/// 日志辅助类
	/// </summary>
	public static class LogHelper
	{
		/// <summary>
		/// 获取当前所使用的 LoggerFactory 对象
		/// </summary>
		public static LoggerFactory HelperLoggerFactory
		{
			get { return LoggerFactory.Current; }
		}

		///<summary>
		/// 为指定的类型返回（创建的或已有的）日志对象
		///</summary>
		public static ILogger LoggerFor<T>()
		{
			if (null == HelperLoggerFactory)
			{
				throw new InvalidOperationException("LoggerFactory is not available at this time. Confirm LoggerFactory.Current has a non-NULL value.");
			}

			return HelperLoggerFactory.CreateLogger(typeof(T));
		}

		/// <summary>
		/// 为实例对象的类型返回（创建的或已有的）日志对象
		/// </summary>
		/// <param name="getTypeFromInstance"></param>
		/// <returns></returns>
		public static ILogger LoggerFor(object getTypeFromInstance)
		{
			if (null == HelperLoggerFactory)
			{
				throw new InvalidOperationException("LoggerFactory is not available at this time. Confirm LoggerFactory.Current has a non-NULL value.");
			}

			return HelperLoggerFactory.CreateLogger(getTypeFromInstance);
		}

		public static ILogger LoggerFor(Type type)
		{
			if (null == HelperLoggerFactory)
			{
				throw new InvalidOperationException("LoggerFactory is not available at this time. Confirm LoggerFactory.Current has a non-NULL value.");
			}

			return HelperLoggerFactory.CreateLogger(type);
		}

		/// <summary>
		/// 记录一条表示错误的日志。
		/// 考虑使用 Exception.Publish 统一处理异常。此方法会直接将该信息记录到日志，且使用 Error 级别
		/// </summary>
		public static void Error<T>(string message, Exception exception)
		{
			var logger = LoggerFor<T>();
			if (null != logger)
			{
				logger.Log(message, exception, OperationProcessLevel.Error);
			}
		}

		public static void Debug<T>(string message)
		{
			var logger = LoggerFor<T>();
			if(null != logger)
			{
				logger.Debug(message);
			}
		}

		#region Trace

		/// <summary>
		/// Traces 消息[Info 级别]，仅当 tracing 启用时才生成消息
		/// 使用此方法来避免过长的调用，比如当 logging 关闭时 "ToDebugString"
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="generateMessage">The delegate to generate a message.</param>
		/// <remarks></remarks>
		public static void Trace<T>(Func<string> generateMessage)
		{
			Trace(typeof(T), generateMessage);
		}
		
		/// <summary>
		/// Traces 消息[Info 级别]，仅当 tracing 启用时才生成消息
		/// 使用此方法来避免过长的调用，比如当 logging 关闭时 "ToDebugString"
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="generateMessage">The delegate to generate a message.</param>
		/// <remarks></remarks>
		public static void Trace(Type callingType, Func<string> generateMessage)
		{
			var logger = LoggerFor(callingType);

			if (null == logger )
			{
				return;
			}

			logger.Info(generateMessage);
		}

		/// <summary>
		/// 记录消息[info]，当 开始 Information 级别时才生成日志
		/// </summary>
		/// <param name="type">The type for the logging namespace.</param>
		/// <param name="generateMessageFormat">The message format.</param>
		/// <param name="formatItems">The format items.</param>
		public static void Trace(Type type, string generateMessageFormat, params Func<object>[] formatItems)
		{
			var logger = LoggerFor(type);

			if (logger == null)
			{
				return;
			}


			if (logger.IsEnabled(OperationProcessLevel.Infomation))
			{
				var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
				logger.Info(generateMessageFormat, executedParams);
			}
		}

		public static void Trace<T>(string message)
		{
			Trace(typeof (T), message);
		}

		public static void Trace(Type type, string message)
		{
			var logger = LoggerFor(type);

			if (null == logger )
			{
				return;
			}

			logger.Info(message);
		}

		#endregion

		#region Warn

		public static void Warn(Type callingType, string message)
		{
			var logger = LoggerFor(callingType);

			if (null == logger)
			{
				return;
			}

			logger.Warn(message);
		}

		public static void Warn(Type callingType, string format, params object[] parts)
		{
			var logger = LoggerFor(callingType);

			if (null == logger)
			{
				return;
			}

			logger.Warn(format, parts);
		}

		/// <summary>
		/// 添加一条表示警告的日志
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="message"></param>
		public static void Warn<T>(string message)
		{
			var logger = LoggerFor<T>();
			if (logger != null)
			{
				logger.Warn(message);
			}
		}

		/// <summary>
		/// 添加一条表示警告的日志
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="format"></param>
		/// <param name="items"></param>
		public static void Warn<T>(string format, params object[] parts)
		{
			var logger = LoggerFor<T>();

			if (null == logger)
			{
				return;
			}

			logger.Warn(format, parts);
		}

		#endregion
	}
}
